﻿using System;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace ASPItalia.ModelVirtualCasting.Silverlight
{
  public class DragManager
  {
    static private bool _isMouseCapured;
    static Point _mouseLastPosition;
    static UIElement _currentDockItem;
    public static readonly DependencyProperty IsDraggableProperty = DependencyProperty.RegisterAttached(
        "IsDraggable",
        typeof(Boolean),
        typeof(DragManager),
        new PropertyMetadata(false)
    );
    public static readonly DependencyProperty IsDragDockProperty = DependencyProperty.RegisterAttached(
        "IsDragDock",
        typeof(Boolean),
        typeof(DragManager),
        new PropertyMetadata(false)
    );

    public static readonly DependencyProperty FilterRightDataProperty = DependencyProperty.RegisterAttached(
        "FilterRightData",
        typeof(bool),
        typeof(DragManager),
        new PropertyMetadata(false));

    public static bool GetFilterRightData(UIElement element)
    {
      return (bool)element.GetValue(FilterRightDataProperty);
    }
    public static void SetFilterRightData(UIElement element, bool value)
    {
      element.SetValue(FilterRightDataProperty, value);
    }

    public static void SetIsDraggable(UIElement element, Boolean value)
    {
      element.SetValue(IsDraggableProperty, value);
      //registrazione eventi
      element.MouseLeftButtonDown += new MouseButtonEventHandler(element_MouseLeftButtonDown);
      element.MouseLeftButtonUp += new MouseButtonEventHandler(element_MouseLeftButtonUp);
      element.MouseMove += new MouseEventHandler(element_MouseMove);
    }
    public static Boolean GetIsDraggable(UIElement element)
    {
      return (Boolean)element.GetValue(IsDraggableProperty);
    }
    public static void SetIsDragDock(UIElement element, Boolean value)
    {
      element.SetValue(IsDragDockProperty, value);
    }
    public static Boolean GetIsDragDock(UIElement element)
    {
      return (Boolean)element.GetValue(IsDragDockProperty);
    }
    static void element_MouseMove(object sender, MouseEventArgs e)
    {
      UIElement _element = (UIElement)sender;
      if (_isMouseCapured)
      {
        TranslateTransform _translateTranform = GetTranslateTransform(_element);

        //modifica la trasformazione per muovere l'oggetto
        _translateTranform.Y += e.GetPosition(null).Y - _mouseLastPosition.Y;
        _translateTranform.X += e.GetPosition(null).X - _mouseLastPosition.X;

        //aggiorna le variabili 
        _mouseLastPosition.X = e.GetPosition(null).X;
        _mouseLastPosition.Y = e.GetPosition(null).Y;

        //trovo le coordinare correnti dell'oggetto
        GeneralTransform _objGeneralTransform = _element.TransformToVisual(Application.Current.RootVisual as UIElement);
        Point _point = _objGeneralTransform.Transform(new Point(0, 0));

        //controllo che tra gli oggetti con cui collido si trovi un "dockItem"
        UIElement u = (from ui in VisualTreeHelper.FindElementsInHostCoordinates(
                    new Rect(_point.X,
                             _point.Y,
                            ((FrameworkElement)_element).ActualWidth,
                            ((FrameworkElement)_element).ActualHeight),
                            (UIElement)VisualTreeHelper.GetParent(_element))
                       where (bool)ui.GetValue(IsDragDockProperty) == true
                       select ui).FirstOrDefault();

        //se trovo qualcosa lo salvo
        if (u != null)
        {
          if (_currentDockItem != u)
          {
            _currentDockItem = u;
          }

          _element.SetValue(FilterRightDataProperty, (bool)u.GetValue(FilterRightDataProperty));
        }
        else
        {
          //altrimento lo resetto
          _currentDockItem = null;
        }
      }
    }
    static void element_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
      //recupero l'oggetto che ha generato l'evento
      UIElement _element = (UIElement)sender;

      //il maouse è libero
      _isMouseCapured = false;
      _element.ReleaseMouseCapture();
      //imposto l'animazione
      if (_currentDockItem == null)
      {
        Storyboard restoreStoryBoard = new Storyboard();
        DoubleAnimation xAnimation = new DoubleAnimation { To = 0, Duration = new Duration(TimeSpan.FromMilliseconds(400)) };
        DoubleAnimation yAnimation = new DoubleAnimation { To = 0, Duration = new Duration(TimeSpan.FromMilliseconds(500)) };
        xAnimation.EasingFunction = new BounceEase { EasingMode = System.Windows.Media.Animation.EasingMode.EaseOut, Bounces = 1, Bounciness = 10 };
        yAnimation.EasingFunction = new BounceEase { EasingMode = System.Windows.Media.Animation.EasingMode.EaseOut, Bounces = 1, Bounciness = 10 };
        Storyboard.SetTarget(xAnimation, _element.RenderTransform);
        Storyboard.SetTargetProperty(xAnimation, new PropertyPath(TranslateTransform.XProperty));
        Storyboard.SetTarget(yAnimation, _element.RenderTransform);
        Storyboard.SetTargetProperty(yAnimation, new PropertyPath(TranslateTransform.YProperty));
        restoreStoryBoard.Children.Add(xAnimation);
        restoreStoryBoard.Children.Add(yAnimation);
        restoreStoryBoard.Begin();
        restoreStoryBoard.Completed += (s, a) => { _element.RenderTransform = null; };
      }
      _currentDockItem = null;
      _mouseLastPosition = new Point();
    }
    static void element_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
      //recupero l'oggetto che ha generato l'evento
      UIElement _element = (UIElement)sender;
      //recupero la sua TranslateTransform
      TranslateTransform _currentTranslateTransform = GetTranslateTransform(_element);
      //recupero la posizione del mouse
      _mouseLastPosition = e.GetPosition(null);
      //catturo il mouse
      _isMouseCapured = true;
      _element.CaptureMouse();
    }
    private static TranslateTransform GetTranslateTransform(UIElement uielement)
    {
      if (uielement == null) throw new ArgumentNullException("uielement");
      TranslateTransform _translateTransform = null;
      //controllo se è applicata solo una trasformazione
      if (uielement.RenderTransform is TranslateTransform)
      {
        //e la restituisco
        _translateTransform = (TranslateTransform)uielement.RenderTransform;
      }
      //altrimenti la cerco nel gruppo delle trasformazioni
      else if (uielement.RenderTransform is TransformGroup)
      {
        TransformGroup _transformGroup = (TransformGroup)uielement.RenderTransform;

        foreach (Transform item in _transformGroup.Children)
        {
          if (item is TranslateTransform)
          {
            //quando la trovo la restituisco
            _translateTransform = (TranslateTransform)item;
          }
        }
      }
      else
      {
        //se non ho trovato  nulla, ne creo una nuova e l'assegno all'oggetto
        _translateTransform = new TranslateTransform();
        uielement.RenderTransform = _translateTransform;
      }
      return _translateTransform;
    }
  }
}
